package juego;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import principal.Constantes;

import niveles.Escenario;
import basicas.Posicion;
import juego.armas.Ametralladora;
import juego.armas.Arma;
import juego.enums.*;

public abstract class Tanque extends ObjetoDelJuego implements IDireccionable, IDestruible, IMovil {
	private int movimientosRestantes;
	private double velocidadMovimiento;
	private tipoMovimiento direccion;
	private Posicion posicionDestino;
	private int tiempoRecarga; // Esto sirve para crear el intervalo entre disparos.
	private int tiempoDisparoRestante; // Esto sirve para crear el intervalo entre disparos.
		
	private int resistencia;
	
	private Arma arma;	
	
	public Tanque(Posicion posicionInicial) {
		super(posicionInicial);
		//setMovimientosRestantes(0);	
		movimientosRestantes = 0;
		setArma(new Ametralladora());
		this.setResistencia(100);
	}
	
	public Tanque(Node n) {
		super(n);
		Node child = null;
		String claseArma;
		
		//child = n.getChildNodes().item(1); // posicion				
		
		child = n.getChildNodes().item(3); // movimientosRestantes
		movimientosRestantes = Integer.parseInt(child.getTextContent());
		
		child = n.getChildNodes().item(5); // velocidadMovimiento
		setVelocidadMovimiento(Double.parseDouble(child.getTextContent()));
		
		child = n.getChildNodes().item(7); // direccion
		if (child.getTextContent().equals("arriba")) {
			setDireccion(tipoMovimiento.arriba);
		} else if (child.getTextContent().equals("abajo")) {
			setDireccion(tipoMovimiento.abajo);
		} else if (child.getTextContent().equals("derecha")) {
			setDireccion(tipoMovimiento.derecha);
		} else if (child.getTextContent().equals("izquierda")) {
			setDireccion(tipoMovimiento.izquierda);
		}
		
		child = n.getChildNodes().item(9); // tiempoRecarga
		setTiempoRecarga(Integer.parseInt(child.getTextContent()));
		
		child = n.getChildNodes().item(11); // tiempoDisparoRestante
		tiempoDisparoRestante = Integer.parseInt(child.getTextContent());
		
		child = n.getChildNodes().item(13); // resistencia
		setResistencia(Integer.parseInt(child.getTextContent()));
		
		child = n.getChildNodes().item(15); // juego.armas.Ametralladora		
		claseArma = child.getNodeName();
		
		Class partypes[] = new Class[1];
		Object arglist[] = new Object[1];
		
		partypes[0] = Node.class;			
		arglist[0] = child;
				
		try {
			setArma((Arma)(Class.forName(claseArma).getConstructor(partypes[0]).newInstance(arglist[0])));
		} catch (Exception e) {		
			e.printStackTrace();
			System.out.println("No existe el arma: '" + claseArma + "'");
			System.exit(Constantes.ERROR_ARMA_INEXISTENTE);
		}
		
		/*for (int i = 0; i < n.getChildNodes().getLength(); i++) {
			Node child = n.getChildNodes().item(i);
			if (child.getNodeName().equals("direccion")) {
				if (child.getTextContent().equals("arriba")) {
					setDireccion(tipoMovimiento.arriba);
				} else if (child.getTextContent().equals("abajo")) {
					setDireccion(tipoMovimiento.abajo);
				} else if (child.getTextContent().equals("derecha")) {
					setDireccion(tipoMovimiento.derecha);
				} else if (child.getTextContent().equals("izquierda")) {
					setDireccion(tipoMovimiento.izquierda);
				}			
			} else if (child.getNodeName().equals("arma")) {
				if (child.getTextContent().equals("ametralladora")) {
					setArma(new Ametralladora());
				} else if (child.getTextContent().equals("canion")) {
					setArma(new Canion());
				} else if (child.getTextContent().equals("lanzaCohetes")) {
					setArma(new LanzaCohetes());
				}
			} else if (child.getNodeName().equals("movimientosRestantes")) {
				movimientosRestantes = Integer.parseInt(child.getTextContent());
			} else if (child.getNodeName().equals("velocidadMovimiento")) {
				setVelocidadMovimiento(Double.parseDouble(child.getTextContent()));
			} else if (child.getNodeName().equals("tiempoRecarga")) {
				setTiempoRecarga(Integer.parseInt(child.getTextContent()));
			} else if (child.getNodeName().equals("resistencia")) {
				setResistencia(Integer.parseInt(child.getTextContent()));
			} else if (child.getNodeName().equals("tiempoDisparoRestante")) {
				tiempoDisparoRestante = Integer.parseInt(child.getTextContent());
			} else if (child.getNodeName().equals("posicionDestino")) {
				setPosicionDestino(new Posicion(Double.parseDouble(child.getChildNodes().item(1).getTextContent()), 
						                        Double.parseDouble(child.getChildNodes().item(3).getTextContent())));
			} else if (child.getNodeName().equals("arma_disparos")) {
				getArma().setCantidadDisparos(Integer.parseInt(child.getTextContent()));
			}
		}*/		
	}

	public void mover(tipoMovimiento direccion) {
		Posicion destino = getPosicion().Copiar();		
		movimientosRestantes = (int)(1/getVelocidadMovimiento());
		setDireccion(direccion);			
		
		switch(getDireccion()) {
			case arriba: destino.mover(0, -1); break;
			case abajo: destino.mover(0, 1); break;
			case derecha: destino.mover(1, 0); break;
			case izquierda: destino.mover(-1, 0); break;
		}	
		setPosicionDestino(destino);
		informarPosicion();
	}

	public void avanzar() {
		switch(getDireccion()) {
			case arriba: getPosicion().mover(0, getVelocidadMovimiento() * -1); break;
			case abajo: getPosicion().mover(0, getVelocidadMovimiento()); break;
			case derecha: getPosicion().mover(getVelocidadMovimiento(), 0); break;
			case izquierda: getPosicion().mover(getVelocidadMovimiento() * -1, 0); break;
		}
		movimientosRestantes = movimientosRestantes - 1;
	}

	public int recibirDanio(int cantidad) {
		resistencia = resistencia - cantidad;
		if (resistencia <= 0) {
			return explotar();
		}
		return 0;
	}

	public int getResistencia() {
		return resistencia;
	}
	
	public void setResistencia(int resistencia) {
		this.resistencia = resistencia;
	}

	public int explotar() {
		morir();
		getNivel().agregarObjetoVivo(new Explosion(getPosicion()));
		return getPuntos();
	}

	public void vivir() {
		// Esto sirve para crear el intervalo entre disparos.
		if (tiempoDisparoRestante > 0) tiempoDisparoRestante = tiempoDisparoRestante - 1; 
	}

	@Override
	public double getVelocidadMovimiento() {
		return velocidadMovimiento;
	}
	
	public tipoMovimiento getDireccion() { 
		return direccion;
	}

	@Override
	public void setDireccion(tipoMovimiento direccion) {
		this.direccion = direccion;		
	}

	public int getMovimientosRestantes() { 
		return movimientosRestantes;
	}

	@Override
	public void setVelocidadMovimiento(double velocidad) {
		velocidadMovimiento = velocidad;		
	}

	@Override
	public void centrar() {
		if (getPosicion() != null) getPosicion().centrar();
	}

	public boolean puedoMover(tipoMovimiento direccion) {	
		return getNivel().sePuedeMover(this, direccion);
	}

	public Posicion getPosicionDestino() {
		return posicionDestino; 
	}
	
	public void setPosicionDestino(Posicion posicion) {
		posicionDestino = posicion; 
	}
	
	public void informarPosicion() {
		super.informarPosicion();
		if (this.getMovimientosRestantes() > 0) {
			if (getNivel() != null) getNivel().reservarPosicion(this);
		}
	}

	public Arma getArma() {
		return arma;
	}

	public void setArma(Arma arma) {
		this.arma = arma;
	}

	public int getTiempoRecarga() {
		return tiempoRecarga;
	}

	public void setTiempoRecarga(int tiempoRecarga) {
		this.tiempoRecarga = tiempoRecarga;
	}
	
	public void disparar() {
		if (tiempoDisparoRestante <= 0) { // Esto sirve para crear el intervalo entre disparos.
			if (getArma().getCantidadDisparos() <= 0) {
				setArma(new Ametralladora());
			}			
			getNivel().agregarObjetoVivo(getArma().disparar(getPosicion(), getDireccion(), getId(), getVelocidadMovimiento() * 1.1));
			tiempoDisparoRestante = tiempoRecarga;			
		}
	}
	
	public void setNivel(Escenario nivel) {
		super.setNivel(nivel);
	}

	public Element getElemento(Document doc) {		
		Element nuevoNodo;
		Element nodoHijo;
		
		nuevoNodo = super.getElemento(doc);
		
		nodoHijo = doc.createElement("movimientosRestantes");
		nuevoNodo.appendChild(nodoHijo);
		nodoHijo.setTextContent(String.valueOf(movimientosRestantes));		
		
		nodoHijo = doc.createElement("velocidadMovimiento");
		nuevoNodo.appendChild(nodoHijo);
		nodoHijo.setTextContent(String.valueOf(velocidadMovimiento));		

		nodoHijo = doc.createElement("direccion");
		nuevoNodo.appendChild(nodoHijo);
		nodoHijo.setTextContent(direccion.name());		
		
		nodoHijo = doc.createElement("tiempoRecarga");
		nuevoNodo.appendChild(nodoHijo);
		nodoHijo.setTextContent(String.valueOf(tiempoRecarga));
		
		nodoHijo = doc.createElement("tiempoDisparoRestante");
		nuevoNodo.appendChild(nodoHijo);
		nodoHijo.setTextContent(String.valueOf(tiempoDisparoRestante));
		
		nodoHijo = doc.createElement("resistencia");
		nuevoNodo.appendChild(nodoHijo);
		nodoHijo.setTextContent(String.valueOf(resistencia));
		
		nuevoNodo.appendChild(arma.getElemento(doc));
		
		if (posicionDestino != null) {
			nodoHijo = posicionDestino.getElemento(doc, "posicionDestino");
			nuevoNodo.appendChild(nodoHijo);
		}
				
		return nuevoNodo;
	}
}
